package com.mach.platform.service;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.mach.platform.domain.base.Menu;
import com.mach.platform.domain.base.Role;
import com.mach.platform.repository.MenuRepo;
import com.mach.platform.utils.RecurFactory;
import com.mach.platform.utils.security.SecurityUtils;
import com.mach.platform.utils.springdata.DynamicSpecifications;
import com.mach.platform.utils.springdata.SearchFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Administrator
 * @Description:
 * @Package: com.model.boyer.service
 * @time 2018/9/21 21:20
 */
@Service
public class MenuServiceImpl implements BaseService<Menu> {

    @Autowired
    private MenuRepo menuRepo;

    @Transactional(rollbackOn = Exception.class)
    @Override
    public Menu save(Menu menu) {
        if (menu.getSort() == null) {
            menu.setSort(1);
        }
        return menuRepo.saveAndFlush(menu);
    }

    @Override
    public List<Menu> insertObjInBatch(List<Menu> list) {
        return null;
    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public Menu update(Menu menu) {
        return menuRepo.saveAndFlush(menu);
    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public int delete(Long[] ids) {

        final int[] flag = {0};
        Stream.of(ids).forEach(id -> {
            String subsetsById = menuRepo.loadMenuSubsetsById(id);

            List<Long> longList = Splitter.on(",").splitToList(subsetsById).stream().filter(item -> !item.equals("") && item !=null ).map(item -> Long.parseLong(item)).collect(Collectors.toList());
            menuRepo.delRelationByMenuIds(longList);
            int in = menuRepo.deleteByIdIn(longList.toArray(new Long[longList.size()]));
            flag[0] = +in;
        });

        return flag[0];
    }


    @Override
    public Page<Menu> list(Pageable pageable, Map params) {
        Specification conditions = DynamicSpecifications
                .bySearchFilter(SearchFilter.parse(params).values(), Role.class);

        Page<Menu> dbResult = menuRepo.findAll(conditions, pageable);

        return dbResult;
    }

    /**
     * 获取 数据
     *
     * @param id 获取详情的id
     * @return
     */
    @Override
    public Menu info(Long id) {
        return null;
    }

    /**
     * 获取菜单角色
     *
     * @return
     */
    public List<Menu> loadMenusRoles() {

        Long operatedId = SecurityUtils.getCurrentUser().getId();
        List<Menu> dbRESULT = menuRepo.loadMenuWithInUserRolds(operatedId);

        // 获取第一级的菜单，调用递归，根据sort排序
        Menu father = dbRESULT.stream().filter(menu -> menu.getPid().equals(0L)).findFirst().get();
        List<Menu> result = Lists.newArrayList();
        result.add(recurMenus(dbRESULT, father));

        return result;

    }

    /**
     * 没有权限限制的菜单数据
     * @return
     */
    public List<Menu> loadMenusTreeNonAuth() {


        List<Menu> dbRESULT = menuRepo.findAll();

        // 获取第一级的菜单，调用递归，根据sort排序
        Menu father = dbRESULT.stream().filter(menu -> menu.getPid().equals(0L)).findFirst().get();
        List<Menu> result = Lists.newArrayList();
        result.add(recurMenus(dbRESULT, father));

        return result;
    }

    public Menu recurMenus(List<Menu> dataStore, Menu father) {

        Menu result = new RecurFactory<Menu>() {
            @Override
            public boolean finish(Menu son, Menu father) {
                return son.getPid().equals(father.getId());
            }

            @Override
            public void handleChildren(List<Menu> t, Menu father) {
                father.setChildren(t);
            }

            @Override
            public Comparator<Menu> sortMethod() {
                return Comparator.comparingInt(Menu::getSort);
            }
        }.build(dataStore, father);

        return result;
    }

    /**
     * 根据角色id 获取对应的菜单
     * @param id
     * @return
     */
    public List loadMenusByRoleId(Long id) {

        List map = menuRepo.loadMenusByRoleId(id);

        return map;
    }

    /**
     * 获取扥请求用户对应的菜单数据
     * @return
     */
    public List loadUserAuthMenus() {

        Long id = SecurityUtils.getCurrentUser().getId();
        List<Menu> dbRESULT = menuRepo.loadUserAuthMenus(id);

        // 获取第一级的菜单，调用递归，根据sort排序
        Menu father = dbRESULT.stream().filter(menu -> menu.getPid().equals(0L)).findFirst().get();
        List<Menu> result = Lists.newArrayList();
        result.add(recurMenus(dbRESULT, father));

        return result;
    }

    /**
     * 获取扥请求用户对应的 共功能 菜单数据
     * @param rootUrl
     * @return
     */
    public List loadUserAuthMenusAndMenus(String rootUrl) {

        String forFuns = menuRepo.loadUserAuthMenusForFuns(rootUrl);
        List<Menu> handleMenus = Lists.newArrayList();
        if (!"".equals(forFuns)) {
            List<Long> targetIds = Splitter.on(",").splitToList(forFuns).stream().filter(hell-> !"".equals(hell)).map(itr -> Long.parseLong(itr)).collect(Collectors.toList());
            Long id = SecurityUtils.getCurrentUser().getId();
            List<Menu> dbResult = menuRepo.loadUserAuthMenus(id);
            if (dbResult.size() > 0) {
                for (int i = 0; i < dbResult.size(); i++) {
                    Menu curMenu = dbResult.get(i);
                    if (targetIds.contains(curMenu.getId())) {
                        handleMenus.add(curMenu);
                    }
                }
            }
        }

        if (handleMenus.size() == 0) {
            return handleMenus;
        } else {
            Menu fatherMenu = menuRepo.findByUrl(rootUrl);
            List<Menu> result = Lists.newArrayList();
            result.add(recurMenus(handleMenus, fatherMenu));
            return result;
        }
    }

}
